package com.gitee.sop.order.pay.base.wx;

import com.gitee.sop.order.pay.base.PayBaseService;
import com.gitee.sop.order.pay.util.XmlUtils;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;


/**
 * 微信支付
 *
 * @author Admin
 */
@Service
public class WxpayServiceImpl implements WxpayService {

    @Autowired
    private PayBaseService payBaseService;

    @Override
    public Map<String, String> preCreate(WeixinOrder weixinOrder) {
        if (weixinOrder == null) {
            return null;
        }
        WeiXinPayConfig weiXinPayConfig = payBaseService.getPayConfig(WeiXinPayConfig.class, "wx");

        String appid = weiXinPayConfig.getAppid();
        String mchId = weiXinPayConfig.getMch_id();
        weixinOrder.setAppid(appid);
        weixinOrder.setMch_id(mchId);
        weixinOrder.setNotify_url(weiXinPayConfig.getNotify_url());
        weixinOrder.setTrade_type("APP");
        weixinOrder.setNonce_str(RandomStringUtils.randomAlphanumeric(20));

        Map<String, String> map = new HashMap();
        BeanMap beanMap = BeanMap.create(weixinOrder);
        for (Object key : beanMap.keySet()) {
            if (null != beanMap.get(key)) {
                map.put(key + "", beanMap.get(key).toString());
            }
        }
        weixinOrder.setSign(createSign(map, weiXinPayConfig.getKey()));
        Map<String, String> data = null;
        String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        MediaType type = MediaType.parse("text/xml");
        String xml = toXml(weixinOrder);
        System.err.println(xml);
        RequestBody requestBody = RequestBody.create(type, xml);
        Request request = new Request.Builder().url(url).post(requestBody).build();
        try {
            Response response = OkHttpUtil.execute(request);
            if (response.isSuccessful()) {
                data = XmlUtils.xmlBody2map(response.body().string(), "xml");
                if (validateSign(data, weiXinPayConfig.getKey())) {
                    Map<String, String> mapPay = new HashMap();
                    if (weixinOrder.getTrade_type().equals("APP")) {
                        mapPay.put("appid", appid);
                        mapPay.put("partnerid", mchId);
                        mapPay.put("prepayid", data.get("prepay_id"));
                        mapPay.put("package", "Sign=WXPay");
                        mapPay.put("noncestr", data.get("nonce_str"));
                        mapPay.put("timestamp", System.currentTimeMillis() / 1000L + "");
                        mapPay.put("sign", data.get("sign"));
                        mapPay.put("sign", createSign(mapPay, weiXinPayConfig.getKey()));
                    } else if (weixinOrder.getTrade_type().equals("JSAPI")) {
                        mapPay.put("appId", appid);
                        mapPay.put("package", "prepay_id=" + data.get("prepay_id"));
                        mapPay.put("signType", "MD5");
                        mapPay.put("nonceStr", data.get("nonce_str"));
                        mapPay.put("timeStamp", System.currentTimeMillis() / 1000L + "");
                        mapPay.put("sign", data.get("sign"));
                    }
                    return mapPay;
                }
                data = null;
            } else {
                throw new IOException("Unexpected code " + response);
            }
        } catch (Exception e) {
            return null;
        }
        return data;
    }

    private String toXml(WeixinOrder orderVO) {
        StringBuffer sb = new StringBuffer();
        sb.append("<xml>");
        BeanMap beanMap = BeanMap.create(orderVO);
        for (Object key : beanMap.keySet()) {
            if (null != beanMap.get(key)) {
                sb.append("<" + key + ">");
                sb.append(beanMap.get(key));
                sb.append("</" + key + ">");
            }
        }
        sb.append("</xml>");
        return sb.toString();
    }

    private String createSign(Map<String, String> map, String wxKey) {
        List<String> list = new ArrayList(map.keySet());
        Collections.sort(list);
        String keyValueStr = "";
        for (String key : list) {
            if ((null != map.get(key)) && (!"sign".equals(key))) {
                keyValueStr = keyValueStr + key + "=" + (String) map.get(key) + "&";
            }
        }
        keyValueStr = keyValueStr + "key=" + wxKey;
        return DigestUtils.md5Hex(keyValueStr).toUpperCase();
    }


    private boolean validateSign(Map<String, String> map, String wxKey) {
        String signRetrun = (String) map.get("sign");
        String sign = createSign(map, wxKey);
        if (sign.equals(signRetrun)) {
            return true;
        }
        return false;
    }
}
